package org.ekstrabilet.user.logic;

import org.ekstrabilet.admin.Row;
import org.ekstrabilet.database.connection.ConnectionManager;
import org.ekstrabilet.main.log.encryption.MD5;
import org.ekstrabilet.user.beans.User;

import java.security.NoSuchAlgorithmException;
import java.sql.*;
import java.util.LinkedList;

/**
 * Singleton, represents logic of a User, provides connection
 * between User object and database, implements methods responsible for
 * manipulating that object in database 
 */
public class UserLogic {

	static private UserLogic userLogic;

	private UserLogic() {

	}

	/**
	 * validate and add user to database
	 * @throws SQLException, NoNoSuchAlgorithmException 
	 * @param user
	 * @return true if succedded
	 */
	public boolean add(User user) {

		if (user.getUserID() < 0 || user.getLogin() == null
				|| user.getName() == null || user.getSname() == null
				|| user.getLogin().length() == 0
				|| user.getName().length() == 0
				|| user.getSname().length() == 0
				|| user.getPassword().length() == 0
				|| user.getType().length() == 0) {
			return false;
		}

		String query = "INSERT INTO user (login, name, sname, password, type)"
				+ " VALUES (?,?,?,?,?)";

		Connection conn = ConnectionManager.getManager().getConnection();
		try {

			PreparedStatement st = conn.prepareStatement(query);

			st.setString(1, user.getLogin());
			st.setString(2, user.getName());
			st.setString(3, user.getSname());
			st.setString(4, MD5.encrypt(user.getPassword()));
			st.setString(5, user.getType());

			st.executeUpdate();
			st.close();

			return true;

		} catch (SQLException e) {
			e.printStackTrace();
			return false;
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}

	}

	/**
	 * deletes user from database
	 * @throws SQLException
	 * @param user
	 * @return true if succedded
	 */
	public boolean delete(User user) {

		Connection conn = null;
		PreparedStatement st = null;
		String query = null;

		try {
			conn = ConnectionManager.getManager().getConnection();
			query = "DELETE FROM user WHERE login = ?";
			st = conn.prepareStatement(query);
			st.setString(1, user.getLogin());
			st.executeUpdate();

			conn.close();

			return true;

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}

	}

	/**
	 * updates user data if already exists in database
	 * adds new user if login was not found 
	 * @throws SQLException, NoNoSuchAlgorithmException
	 * @param user
	 * @return true if succedded
	 */
	public boolean update(User user) {

		Connection conn = null;
		PreparedStatement st = null;
		ResultSet rs = null;
		String query = null;

		if (user.getLogin() == null) {
			return false;
		}

		try {
			// check if user exists in database
			conn = ConnectionManager.getManager().getConnection();
			query = "SELECT login FROM user WHERE login=(?)";
			st = conn.prepareStatement(query);
			st.setString(1, user.getLogin());
			rs = st.executeQuery();

			if (rs.next()) {
				// update

				if (user.getName() == null || user.getSname() == null
						|| user.getLogin().length() == 0
						|| user.getName().length() == 0
						|| user.getSname().length() == 0
						|| user.getPassword().length() == 0
						|| user.getType().length() == 0) {
					return false;
				}

				query = "UPDATE user SET name = ?, sname = ?, password = ?, type = ? WHERE login = ?";
				st = conn.prepareStatement(query);

				st.setString(1, user.getName());
				st.setString(2, user.getSname());
				st.setString(3, MD5.encrypt(user.getPassword()));
				st.setString(4, user.getType());
				st.setString(5, user.getLogin());
				st.executeUpdate();

				conn.close();
				rs.close();
				st.close();

				return true;

			} else {
				// add
				add(user);
			}

		} catch (SQLException e) {
			e.printStackTrace();
			return false;
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			return false;
		}

		return false;

	}

	/**
	 * check if user and password is correct and logs in
	 * @throws SQLException, NoNoSuchAlgorithmException
	 * @param user
	 * @return true if succeded
	 */
	public User login(String login, String password) {



	
			Connection conn = null;
			PreparedStatement st = null;
			ResultSet rs = null;
			String query;

			try {
				conn = ConnectionManager.getManager().getConnection();
				query = "SELECT * FROM user WHERE login = ?";
				st = conn.prepareStatement(query);
				st.setString(1, login);
				rs = st.executeQuery();

				if (rs.next()) {
					if (login.equals(rs.getString("login"))) {
						if (MD5.encrypt(password).equals(
								rs.getString("password"))){
							User user= new User();
							user.setLogin(login);
							user.setType(rs.getString("type"));
							user.setName(rs.getString("name"));
							user.setSname(rs.getString("sname"));
							return user;
						}
							
									
						 else {
							return null;
						}
					}
				}

			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return null;
			} catch (NoSuchAlgorithmException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return null;
			}
		
		return null;
	}

	/**
	 * gets list of users from database
	 * @throws SQLException
	 * @return list of all users 
	 */
	public LinkedList<User> getUsers() {

		String query = "Select * from user";

		LinkedList<User> usersList = new LinkedList<User>();
		Connection conn = ConnectionManager.getManager().getConnection();
		try {
			Statement st = conn.createStatement();
			ResultSet rs = st.executeQuery(query);

			User user;
			while (rs.next()) {
				user = new User();
				user.setUserID(rs.getInt("userID"));
				user.setLogin(rs.getString("login"));
				user.setName(rs.getString("name"));
				user.setSname(rs.getString("sname"));
				user.setPassword(rs.getString("password"));
				user.setType(rs.getString("type"));
				usersList.add(user);
			}
			conn.close();

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return usersList;

	}

	/**
	 * @return instance of UserLogic
	 */
	static public UserLogic getInstance() {
		if (userLogic == null) {
			userLogic = new UserLogic();
		}
		return userLogic;
	}

	/**
	 * creates new user instance
	 * @param row
	 * @param pass - password
	 * @return user instance
	 */
	static public User initUser(Row row, String pass) {
		User u = new User();
		u.setLogin(row.getLogin());
		u.setName(row.getName());
		u.setSname(row.getSurname());
		u.setType(row.getType());
		if (pass != null && pass.length() > 0)
			u.setPassword(pass);

		return u;
	}
}
